package com.brooks.demo.program.p1;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * 面试题
 * 实现一个容器，提供两个方法，add,size
 * 写两个线程，线程1往容器里添加10个元素，线程2实现监控元素的个数，当个数到5时，线程2给出提示并结束
 *
 *  这个是利用了wait和notify，到5的时候让t1去叫醒t2，然后t1 wait
 *  t2 获取锁继续执行，执行完了之后叫醒t1，t1获取锁再继续执行
 * @Author mihutu
 * @Date 2020/10/20 11:11
 * @Version 1.0
 */
public class DemoNotify {
    /**
     * 这里使用同步容器来保证数据一致,否则会出现脏读的情况
     */
    volatile List list = Collections.synchronizedList(new LinkedList<>());

    public void add(Object o) {
        list.add(o);
    }

    public int size() {
        return list.size();
    }

    public static void main(String[] args) {

        final Object lock = new Object();

        DemoNotify v = new DemoNotify();

        new Thread(() -> {
            System.out.println("t2监控已启动");
            synchronized (lock) {
                if (v.size() != 5) {
                    try {
                        System.out.println("元素还不到5，我要睡觉了，到5了叫醒我");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("已经到5了，我结束了，你接着添加吧");
                lock.notify();
            }
        }, "t2").start();

        new Thread(() -> {
            System.out.println("t1已启动，准备添加元素");
            synchronized (lock) {
                for (int i = 0; i < 10; i++) {
                    v.add(new Object());
                    System.out.println("添加了第" + i + "个元素");
                    if(v.size()==5){
                        System.out.println("到5了该去叫醒t2了");
                        lock.notify();
                        try {
                            System.out.println("我也也睡一会儿，t2干完活给我叫起来哦");
                            //这里是因为notify不会释放锁，如果不wait，那么t2会等到t1添加完后才能获取到锁
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            System.out.println("t1 结束");
        }, "t1").start();
    }
}
